package main

import (
	"context"
	"fmt"
	"sync"
	"time"

	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/mvcc/mvccpb"
)

type ServicesInfo struct {
	Name    string
	Address map[string]string
	Mutex   sync.Mutex
}

func main() {
	var (
		path  string
		infos *ServicesInfo
	)

	path = "/usr/lists"

	infos = &ServicesInfo{
		Name:    path,
		Address: make(map[string]string),
	}

	getResources(infos)
}

func getResources(infos *ServicesInfo) {
	var (
		conf    clientv3.Config
		client  *clientv3.Client
		err     error
		kv      clientv3.KV
		getRsp  *clientv3.GetResponse
		item    *mvccpb.KeyValue
		watcher clientv3.Watcher
		watcha  clientv3.WatchChan
		event   *clientv3.Event
	)
	//=====================get infos from etcd
	conf = clientv3.Config{
		Endpoints:   []string{"127.0.0.1:2379"},
		DialTimeout: 5 * time.Second,
	}

	//new client
	if client, err = clientv3.New(conf); err != nil {
		fmt.Println(err)
		return
	}

	kv = clientv3.NewKV(client)
	if getRsp, err = kv.Get(context.TODO(), infos.Name, clientv3.WithPrefix()); err != nil {
		return
	}

	infos.Mutex.Lock()
	for _, item = range getRsp.Kvs {
		infos.Address[string(item.Key)] = string(item.Value)
	}
	infos.Mutex.Unlock()

	fmt.Println(infos.Address)
	//==========================watcher the items changes

	watcher = clientv3.NewWatcher(client)
	watcha = watcher.Watch(context.TODO(), infos.Name, clientv3.WithPrefix())
	for watRsp := range watcha {
		fmt.Printf("%d rep\n", watRsp.Header.Revision)
		for _, event = range watRsp.Events {
			infos.Mutex.Lock()
			switch event.Type {
			case mvccpb.PUT:
				infos.Address[string(event.Kv.Key)] = string(event.Kv.Value)
				fmt.Println("=================PUT")
				fmt.Println(infos.Address)
			case mvccpb.DELETE:
				delete(infos.Address, string(event.Kv.Key))
				fmt.Println("=================DEL")
				fmt.Println(infos.Address)
			}
			infos.Mutex.Unlock()
		}
	}
}
